package com.lcc.springconfig.controller;

import com.lcc.springconfig.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@RequestMapping("/scope")
public class BeanScopeController {
    @Autowired
    private ApplicationContext context;

    @Resource(name = "singleUser")//存在两个返回类型为User的方法，此时通过Autowired就匹配不了正确的，故使用Resource实现利用名称进行匹配
    private User singleUser;

    @Resource(name = "protoTypeUser")
    private User protoTypeUser;

    @Resource(name = "requestUser")
    private User requestUser;

    @Resource(name = "sessionUser")
    private User sessionUser;

    @Resource(name = "applicationUser")
    private User applicationUser;
    /**
     * 单例作用域
     * 从context中获取对象
     * 属性注入获取对象
     */
    @RequestMapping("/single")
    public String single(){
        User user = (User) context.getBean("singleUser");
        return "context获取到的对象：" + System.identityHashCode(user) + ",注解获取到的对象：" + System.identityHashCode(singleUser);
    }
    /**
     * 多礼作用域
     * 从context中获取对象
     * 属性注入获取对象
     */
    @RequestMapping("/protoType")
    public String protoType(){
        User user = (User) context.getBean("protoTypeUser");
        return "context获取到的对象：" + System.identityHashCode(user) + ",注解获取到的对象：" + System.identityHashCode(protoTypeUser);
    }

    /**
     * 请求作用域
     * 从context中获取对象
     * 属性注入获取对象
     */
    @RequestMapping("/request")
    public String request(){
        //此时生成一个代理类
        User user = (User) context.getBean("requestUser");
        //打印new User()的内存地址，在堆中
        //所以大发生新的请求，生成二等对象的内存地址还是不变的
//        return "context获取到的对象：" + System.identityHashCode(user) + ",注解获取到的对象：" + System.identityHashCode(requestUser);
        //打印User user = new User()的user应用地址，存放在栈中
        //此时的对象的引用地址会在不同的请求中产生不同的结果
        System.out.println(user.toString());//代理类重写目标类的toString方法，输出的是代理类的类名和内存地址，不会在不同请求发生变化
        System.out.println(user.getClass().getName() + "@" + Integer.toHexString(user.hashCode()));//目标类的类名和内存地址，不同请求生成不同的对象，所以内存地址发生变化
        return "context获取到的对象：" + user + ",注解获取到的对象：" + requestUser;

    }

    /**
     * 多例作用域
     * 从context中获取对象
     * 属性注入获取对象
     */
    @RequestMapping("/session")
    public String session(){
        User user = (User) context.getBean("sessionUser");
//        return "context获取到的对象：" + System.identityHashCode(user) + ",注解获取到的对象：" + System.identityHashCode(sessionUser);
        return "context获取到的对象：" + user + ",注解获取到的对象：" + sessionUser;
    }

    /**
     * 多礼作用域
     * 从context中获取对象
     * 属性注入获取对象
     */
    @RequestMapping("/application")
    public String application(){
        User user = (User) context.getBean("applicationUser");
//        return "context获取到的对象：" + System.identityHashCode(user) + ",注解获取到的对象：" + System.identityHashCode(applicationUser);
        return "context获取到的对象：" + user + ",注解获取到的对象：" + applicationUser;
    }
}
